package com.gxar.file.server.base.controller;

import com.alibaba.fastjson.JSON;
import com.gxar.common.entity.Result;
import com.gxar.common.entity.login.LoginUserThread;
import com.gxar.common.entity.login.UserProfile;
import com.gxar.file.server.base.common.enums.ProductEnum;
import com.gxar.file.server.base.common.properties.UserProperties;
import com.gxar.file.server.base.model.ResultCodeEnum;
import com.gxar.file.server.base.model.download.DownloadRequest;
import com.gxar.file.server.base.model.upload.request.UploadRequest;
import com.gxar.file.server.base.model.upload.response.UploadResponse;

import com.gxar.file.server.db.model.FileEntity;
import com.gxar.file.server.db.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Objects;
import java.util.Optional;


/**
 * 素材视图控制器
 *
 * @author Linsy
 * @version 1.0
 * @created 2023/6/20
 */
@Api(tags = "单个文件视图控制器")
@RestController
@RequestMapping("/api/file")
@RequiredArgsConstructor
@Slf4j
public class FileController {

    private final FileService fileService;
    private final UserProperties userProperties;

    @ApiOperation("上传文件")
    @PostMapping(value = "/upload")
    @ResponseBody
    public Result<UploadResponse> upload(@Valid UploadRequest uploadRequest, @RequestParam(name = "file", required = false) MultipartFile file) {
        try {
            UserProfile userProfile = LoginUserThread.get();
            if (file != null) {
                Optional<ProductEnum> productEnumOptional = ProductEnum.getByName(uploadRequest.getProduct());
                if (!productEnumOptional.isPresent()) {
                    return Result.error(ResultCodeEnum.TEMPORARILY_UNAVAILABLE);
                }
                ProductEnum product = productEnumOptional.get();
                //图片文件处理
                String originalFilename = file.getOriginalFilename();
                String suffix = null;
                if (StringUtils.isNotBlank(originalFilename)) {
                    log.info("文件名：[{}]", originalFilename);
                    suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
                }
                if (StringUtils.isNotBlank(originalFilename)) {
                    originalFilename = originalFilename.substring(0, originalFilename.lastIndexOf("."));
                }
                StringBuilder directory = new StringBuilder();
                if (Objects.nonNull(userProfile)) {
                    directory.append("/").append(userProfile.getId());
                }
                if (StringUtils.isNotBlank(uploadRequest.getDirectory())) {
                    String fileDirectory = uploadRequest.getDirectory();
                    if (fileDirectory.startsWith("/")) {
                        fileDirectory = fileDirectory.substring(1);
                    }
                    if (fileDirectory.endsWith("/")) {
                        fileDirectory = fileDirectory.substring(0, fileDirectory.length() - 1);
                    }
                    directory.append("/").append(fileDirectory);
                }
                String name = "product/" + product.getName() + directory + "/" + originalFilename + "-" + System.currentTimeMillis() + suffix;
                Boolean isUpload = fileService.upload(product, name, originalFilename, file, uploadRequest.getPublics(), userProfile);
                if (isUpload) {
                    UploadResponse uploadResponse = new UploadResponse();
                    uploadResponse.setName(name);
                    // 公共读才有办法通过url访问
                    if (Objects.nonNull(uploadRequest.getPublics()) && uploadRequest.getPublics()) {
                        uploadResponse.setUrl(fileService.getUploadUrl(product, name));
                    }
                    return Result.success(uploadResponse);
                } else {
                    return Result.error(ResultCodeEnum.UPLOAD_FAIL);
                }
            }
        } catch (Exception e) {
            log.error("文件上传异常：{}", e.getMessage(), e);
            return Result.error(ResultCodeEnum.UPLOAD_EXCEPTION);
        }
        return Result.success();
    }

    @ApiOperation("下载文件")
    @PostMapping(value = "/download")
    public void downloadFile(HttpServletRequest request, HttpServletResponse response, DownloadRequest downloadRequest) {
        download(response, downloadRequest.getProduct(), downloadRequest.getName());
    }

    @ApiOperation("下载文件")
    @GetMapping(value = "/download")
    public void getFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("product") String productName, @RequestParam("name") String name) {
        download(response, productName, name);
    }

    /**
     * 下载文件
     *
     * @param response    响应
     * @param productName 产品名称
     * @param name        文件名称
     */
    private void download(HttpServletResponse response, String productName, String name) {
        try {
            Optional<ProductEnum> productEnumOptional = ProductEnum.getByName(productName);
            if (!productEnumOptional.isPresent()) {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer1 = response.getWriter();
                writer1.write(JSON.toJSONString(Result.error(ResultCodeEnum.TEMPORARILY_UNAVAILABLE)));
                writer1.flush();
                writer1.close();
                return;
            }
            ProductEnum product = productEnumOptional.get();
            UserProfile userProfile = LoginUserThread.get();
            if (userProfile == null) {
                userProfile = new UserProfile();
                userProfile.setId(userProperties.getDefaultId());
            }
            FileEntity fileEntity = fileService.findByUserIdAndName(userProfile.getId(), product.getName(), name);
            if (Objects.isNull(fileEntity)) {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer1 = response.getWriter();
                writer1.write(JSON.toJSONString(Result.error(ResultCodeEnum.FILE_NOT_EXISTS)));
                writer1.flush();
                writer1.close();
                return;
            }
            String suffix = fileEntity.getName().substring(fileEntity.getName().lastIndexOf("."));
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileEntity.getOriginalFilename(), "UTF-8") + suffix);
            String errorMsg = fileService.downloadFile(product, fileEntity.getName(), response);
            if (StringUtils.isNotBlank(errorMsg)) {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer1 = response.getWriter();
                writer1.write(JSON.toJSONString(Result.error(MessageFormat.format("下载文件失败，解析文件：{0} 异常", name))));
                writer1.flush();
                writer1.close();
                return;
            }
            response.flushBuffer();
        } catch (Exception e) {
            response.setContentType("application/json;charset=UTF-8");
            try {
                PrintWriter writer = response.getWriter();
                writer.write(JSON.toJSONString(Result.error(ResultCodeEnum.UPLOAD_EXCEPTION)));
                writer.flush();
                writer.close();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }
}
